package org.dioib.practice.common.exception.handler;

import org.dioib.practice.common.ApiResponse;
import org.dioib.practice.common.exception.ValidationErrorResponse;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;

@RestControllerAdvice
public class ValidationExceptionHandler {


    private final MessageSource messageSource;


    public ValidationExceptionHandler(MessageSource messageSource) {
        this.messageSource = messageSource;
    }


    @ExceptionHandler(BindException.class)
    public ResponseEntity<ValidationErrorResponse> handleBindException(BindException ex) {
        List<FieldErrorDetail> fieldErrors = ex.getFieldErrors().stream()
                .map(fieldError -> {
                    String message = getLocalizedMessage(fieldError.getDefaultMessage());
                    return new FieldErrorDetail(
                            fieldError.getField(),
                            fieldError.getRejectedValue(),
                            message
                    );
                })
                .collect(Collectors.toList());

//        private String field;
//        private String message;
//        private Object rejectedValue;
//        private String constraint;

//Spring FieldError
//        private final String field;
//        @Nullable
//        private final Object rejectedValue;
//        private final boolean bindingFailure;

        ValidationErrorResponse response = ValidationErrorResponse.builder()
                .timestamp(java.time.LocalDateTime.now())
                .status(HttpStatus.BAD_REQUEST.value())
                .code("Validation Failed")
                .message("输入参数验证失败")
                .fieldErrors(ex.getFieldErrors().stream().map(field->{
                    return new ValidationErrorResponse.FieldError(field.getField(),
                            field.getDefaultMessage(),field.getRejectedValue(),field.getCode());
                }).collect(Collectors.toList()))
                .build();


        return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
    }


    private String getLocalizedMessage(String messageKey) {
        if (messageKey == null) {
            return "未知错误";
        }
        try {
            Locale locale = LocaleContextHolder.getLocale();
            return messageSource.getMessage(messageKey, null, locale);
        } catch (Exception e) {
            return messageKey;
        }
    }
    @ExceptionHandler(DataIntegrityViolationException.class)
    public ResponseEntity<ApiResponse<?>> handleDataIntegrityViolation(
            DataIntegrityViolationException ex, WebRequest request) {

        String rootMsg = ex.getRootCause() != null ? ex.getRootCause().getMessage() : ex.getMessage();
        String userMessage = extractUserFriendlyMessage(rootMsg);


        ApiResponse<?> response = ApiResponse.error(
                        HttpStatus.CONFLICT.value(),
                        "DATA_INTEGRITY_VIOLATION",
                        userMessage,
                        null
                );
        response.setTimestamp(LocalDateTime.now());
        response.setPath(request.getDescription(false));

        return new ResponseEntity<>(response, HttpStatus.CONFLICT);
    }


    private String extractUserFriendlyMessage(String technicalMessage) {
        if (technicalMessage.contains("duplicate key")) {
            return "数据已存在，请勿重复添加";
        } else if (technicalMessage.contains("foreign key constraint")) {
            return "关联数据不存在";
        } else if (technicalMessage.contains("null value")) {
            return "必填字段不能为空";
        }
        return "数据操作冲突，请检查输入数据";
    }
}